#!/usr/bin/env python

# Copyright (c) 2011, 2012 Nathan Grubb
# Available under the new BSD license; see LICENSE.txt

"""grubbot.py: Main executable for the bot, which ties the whole program together."""

import os 

import lib.config
import lib.connection
import lib.message
import lib.plugin

class Grubbot(object):
    """Glues together the bot - contains the read -> parse -> dispatch loop,
       a couple misc. functions, and state information.
    """

    def __init__(self):
        self.grubbot_dir = os.getcwd() # Should be a more complete version...
        self.plugin_dir = os.path.join(self.grubbot_dir, "plugins")
        self.connection = lib.connection.Connection(self)
        self.config = lib.config.Config(self)
        self.config.load()
        self.nickname = self.config.values["nickname"]
        self.sessions = {} # Keep track of logged in users
        # Dictionary of channels and their users, in the format
        # channel: [list of users]
        self.users = {}
        self.plugin = lib.plugin.PluginLoader(self)
        self.plugin.load()

    def exit(self):
        """Closes the bot, and gives all plugins a chance to properly exit (for 
           example, if a plugin should close a database handle) by calling their
           optional close() method.
        """

        plugins = self.plugin.command_plugins.values()

        for ircplugin in self.plugin.irc_plugins:
            for ircpluginobj in ircplugin:
                plugins.append(ircpluginobj)
        
        for plugin in plugins:
            try:
                func = getattr(plugin, "close")
            except AttributeError:
                pass
            else:
                func()

        #self.connection.close() # FIXME Causes a socket.error
        exit(0)

    def write_error(self, obj, error):
        """Simple function to log errors detected by internal code. This is not
           really meant for use by plugins.
        """

        classname = obj.__class__.__name__
        line = "[%s] %s" % (classname, error)
        file = open("error.txt", "a")
        file.write(line+"\n")
        file.close()
        print line

    def connect(self):
        """Set up a connection to the server and login the client."""

        self.connection.connect(self.config.values["network"], self.config.values["port"])

        if self.config.values["password"]:
            self.connection.send("pass", self.config.values["password"])
        self.connection.send("nick", self.config.values["nickname"])
        self.connection.send("user", self.config.values["username"], "*", "*", 
                             self.config.values["realname"])

        for channel in self.config.values["channels"]:
            self.connection.send("join", channel)

    def run(self):
        """Runs the main read -> parse -> dispatch loop."""

        while True:
            line = self.connection.read()
            msg = lib.message.Message.parse(line)
            self.plugin.dispatch(msg)
            
def main():
    grubbot = Grubbot()
    grubbot.connect()
    grubbot.run()

if __name__ == "__main__":
    main()